#ifndef add_file_H
#define add_file_H

#include <string>
#include <sstream>
#include <iostream>
#include "serialization.h"

enum Command {ADD_FILE, CHECKOUT, CHECKIN, GET, VIEW_FILES, VIEW_VERSIONS, UPDATE_OWNER, UNDO_CHECKOUT, VIEW_MY_CO, DEBUG_PRINT_MESSAGE,
FILE_ALREADY_EXISTS, BEGIN_UPLOAD, ACCES_DENIED, ASK_FOR_DOWNLOAD, FILES_LIST, FILES_LIST_LINE, VERSIONS_LIST, VERSIONS_LIST_LINE, OPERATION_SUCCESS,
CO_LIST, CO_LIST_LINE};

namespace commands
{

std::string typeOnlyCommand(Command c);

struct genericCommand
{
    std::stringstream ss;

    genericCommand() {}
    genericCommand(std::string s) : ss(s) {}

    genericCommand& addType(Command c) {addInt(static_cast<int>(c)); return *this;}
    genericCommand& addInt(int a) { ss << ' ' << a << ' '; return *this;}
    genericCommand& addString(std::string s) { ss << Serialize(s); return *this;}

    Command getType() { return static_cast<Command>(getInt()); }
    int getInt() { int a; ss >> a; return a; }
    std::string getString(bool &ok);
    std::string getString();

    std::string serialize() { return ss.str();}
};

struct BeginUpload
{
    BeginUpload(int port);
    BeginUpload(std::string str); // unserialize
    int port;
    Command type;
    std::string serialize();
};

struct AskForDownload
{
    AskForDownload(int fileSize);
    AskForDownload(std::string str); // unserialize
    int fileSize;
    Command type;
    std::string serialize();
};


struct Checkout
{
    Command type;
    std::string username;
    std::string filename;
    Checkout(std::string username, std::string filename);
    Checkout(std::string str); // unserialize

    std::string serialize();
};

struct AddFile
{
    Command type;
    std::string username;
    int fileSize;
    std::string filename;


    AddFile(std::string username, int fileSize, std::string filename);
    AddFile(std::string str); // unserialize

    std::string serialize();
};

}


#endif // add_file_H
